#include "evaluation.h"


//遍历vector中的expression并重新放到map中
evaluation::evaluation(const std::vector<expression> &exprs) {
  for (const auto &expr : exprs) {
    // we do not want expression to have default constructor!
    // thus cannot use operator[], which requires that
    exprs_.insert(std::make_pair(expr.expr_id_, expr));
  }
}

void evaluation::add_kwargs_double(const char *key, double value) {
  args_[key] = tensor(value);
}

void evaluation::add_kwargs_ndarray(const char *key, int dim, size_t shape[],
                                    double data[]) {
  args_[key] = tensor(dim, shape, data);
}

int evaluation::execute() {
  if (exprs_.empty()) {
    printf("evaluation %p: error: no expression\n", this);
    return -1;
  }
  std::map<std::string, tensor>::iterator pos_w;
  std::map<std::string, tensor>::iterator pos_b;
  std::map<std::string, int>::iterator pos_k;
  std::map<std::string, int>::iterator pos_s;
  // std::map<std::string, int>::iterator pos_i;
  // std::map<std::string, int>::iterator pos_o;


  for (auto &p : exprs_) {
    auto &expr = p.second;
    switch (expr.op_type_[0]) {
    case 'I':
      if(expr.op_type_.length() == 5){
          expr.result_ = args_[expr.op_name_];
      }else{
          expr.result_ = Inut2d(args_[expr.op_name_]);
      }
      break;
    case '2':
      expr.result_ = Inut2d(exprs_.find(expr.inputs_[0])->second.result_);
      break;
    case 'C':
      // pos_w = expr.result_wb.find("weight");
      // pos_b = expr.result_wb.find("bias");
      // pos_k = expr.ker_and_str.find("kernel_size");
      // pos_i = expr.ker_and_str.find("in_channels");
      // pos_o = expr.ker_and_str.find("out_channels");
      // expr.result_ = Conv2d(exprs_.find(expr.inputs_[0])->second.result_,
      //                       (*pos_i).second,
      //                       (*pos_o).second,
      //                       (*pos_k).second,
      //                       (*pos_w).second,
      //                       (*pos_b).second
      //                       );
      break;
    case 'A':
      // same here, cannot use operator[]
      //从之前Input存储的输入操作数中找和name对应的操作数，计算后保存结果
      expr.result_ = exprs_.find(expr.inputs_[0])->second.result_   +   exprs_.find(expr.inputs_[1])->second.result_;
      break;
    case 'S':
      expr.result_ = exprs_.find(expr.inputs_[0])->second.result_   -   exprs_.find(expr.inputs_[1])->second.result_;
      break;
    case 'M':
      if(expr.op_type_.length() == 3){
          expr.result_ = exprs_.find(expr.inputs_[0])->second.result_   *   exprs_.find(expr.inputs_[1])->second.result_;
      }else{
         pos_k = expr.ker_and_str.find("kernel_size");
         pos_s = expr.ker_and_str.find("stride");
         expr.result_ = MaxPool2d(exprs_.find(expr.inputs_[0])->second.result_,(*pos_k).second,(*pos_s).second );
      }
      break;
    case 'N':
      // not implemented
      break;
    case 'R':
      expr.result_ = ReLU(exprs_.find(expr.inputs_[0])->second.result_);
      break;
    case 'F':
      expr.result_ = Flatten(exprs_.find(expr.inputs_[0])->second.result_);
      break;
    case 'L':
      pos_w = expr.result_wb.find("weight");
      pos_b = expr.result_wb.find("bias");
      expr.result_ = Linear((*pos_w).second,
                            exprs_.find(expr.inputs_[0])->second.result_,   
                            (*pos_b).second);
       break;                      
    default:
      break;
    }
  }
  return 0;
}

tensor &evaluation::get_result() { return exprs_.rbegin()->second.result_; }
